﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using IBoLT.HelperClasses;

namespace IBoLT.Fractals
{
	public class Leaves
	{
		// Исходная текстура
		private Bitmap texture;
		// Размеры текстуры
		private int width = 200;
		private int height = 200;

		// Максимально возможные коэффициенты умножения расчётных координат
		private Double MaxcMWidth = 40;
		private Double MaxcMHeight = 19;

		public Double MaxCMWidth
		{ get { return MaxcMWidth; } }
		public Double MaxCMHeight
		{ get { return MaxcMHeight; } }

		public Bitmap Texture
		{
			get { return texture; }
			set
			{
				texture = value;
				if (width != texture.Width || height != texture.Height)
				{
					width = texture.Width;
					height = texture.Height;
					Double w = MaxcMWidth;
					Double h = MaxcMHeight;
					MaxcMWidth = (double)width / 5;
					MaxcMHeight = (double)(height - indentH) / 10;
					cMWidth = cMWidth * (double)(MaxcMWidth / w);
					cMHeight = cMHeight * (double)(MaxcMHeight / h);
				}
				//System.Windows.MessageBox.Show(MaxcMWidth.ToString() + " " + MaxcMHeight.ToString());
			}
		}

		// Отступ от верхней границы
		private int indentH = 10;

		// Коэффициенты умножения расчётных координат
		private Double cMWidth = 20;
		private Double cMHeight = 9.5;

		public Double CMWidth
		{
			get { return cMWidth; }
			set
			{
				cMWidth = Math.Max(Math.Min(MaxcMWidth, value), 0.5);
			}
		}
		public Double CMHeight
		{
			get { return cMHeight; }
			set
			{
				cMHeight = Math.Max(Math.Min(MaxcMHeight, value), 0.5);
			}
		}
		
		// Коэффициенты для вычисления координат нового пикселя
		private static double[,] fernCoef = {	{ 0.85,	 0.04,	0.00,	-0.04,	0.85,	1.60,},
												{ 0.20,	-0.26,	0.00,	 0.23,	0.22,	1.60,},
												{-0.15,	 0.28,	0.00,	 0.26,	0.24,	0.44,},
												{ 0.00,	 0.00,	0.00,	 0.00,	0.16,	0.00,}	};

		// Делегат для установки функции фрактала
		public delegate Double[,] delegateTypeLeaf(Double[,] p, int iterations);
		public delegateTypeLeaf delgateTypeL;

		// Палитра для раскраски
		public Int32[] palette = {-16760832, -15452368};

		// Количество итераций
		public int iterations = 100000;

		public Leaves () {}

		public Bitmap Calculate()
		{
			BitmapData bmd = SystemDrawingHelper.LockImage(texture);
			int size = SystemDrawingHelper.GetPixelSize(bmd);

			Double[] p = {0,0};
			Random rndm = new Random();
			//double maxx = 0, maxy = 0;
			for (int i = 0; i < iterations; ++i)
			{
				Int32 leaf = rndm.Next(100);

				if (leaf <= 85)
				{
					p = fern(p, 0);
					SystemDrawingHelper.SetPixel(bmd, width / 2 + (int)(p[0] * cMWidth), height - indentH - (int)(p[1] * cMHeight), Color.FromArgb(palette[0]), size);
				}
				else if (leaf < 93)
				{
					p = fern(p, 1);
					SystemDrawingHelper.SetPixel(bmd, width / 2 + (int)(p[0] * cMWidth), height - indentH - (int)(p[1] * cMHeight), Color.FromArgb(palette[0]), size);
				}
				else if (leaf < 99)
				{
					p = fern(p, 2);
					SystemDrawingHelper.SetPixel(bmd, width / 2 + (int)(p[0] * cMWidth), height - indentH - (int)(p[1] * cMHeight), Color.FromArgb(palette[0]), size);
				}
				else
				{
					p = fern(p, 3);
					SystemDrawingHelper.SetPixel(bmd, width / 2 + (int)(p[0] * cMWidth), height - indentH - (int)(p[1] * cMHeight), Color.FromArgb(palette[1]), size);
				}

				//maxx = (maxx < p[0]) ? p[0] : maxx;
				//maxy = (maxy < p[1]) ? p[1] : maxy;
			}

			SystemDrawingHelper.UnlockImage(texture, bmd);
			//System.Windows.MessageBox.Show(cMWidth.ToString() + " " + cMHeight.ToString());
			return texture;
		}



		public Double[] fern(Double[] p, int rowCoef)
		{
			Double[] p1 = { 0, 0 };
			p1[0] = (p[0] * fernCoef[rowCoef, 0] + p[1] * fernCoef[rowCoef, 1] + fernCoef[rowCoef, 2]);
			p1[1] = (p[0] * fernCoef[rowCoef, 3] + p[1] * fernCoef[rowCoef, 4] + fernCoef[rowCoef, 5]);
			
			return p1;
		}
	}
}